import json
from typing import Dict, Any

from prompt_templates import PLANNING_PROMPT_TEMPLATE
from knowledge_base import retrieve_knowledge


def _call_simulated_llm(prompt: str) -> str:
    """
    这是一个对大型语言模型（LLM）调用的**模拟**。
    在现实应用中，需要将其替换为对Google Gemini API、OpenAI GPT或其他LLM服务的API调用。

    该函数基于Prompt中的关键词返回一个预定义的JSON字符串，以模仿真实LLM生成规划的行为。
    """
    print("\n--- [LLM] 已发送Prompt至模拟LLM ---")
    print(prompt)
    print("--- [LLM] Prompt结束 --- \n")
    print("--- [LLM] 等待模拟LLM响应... ---")

    # 根据Prompt中的目标，模拟LLM的响应
    if "learn data analysis" in prompt.lower() or "学习数据分析" in prompt.lower():
        return json.dumps({
            "plan_title": "成为数据分析师的全面学习路径",
            "plan_summary": "本计划提供了一个结构化的、分步的指南，从编程基础一直到找到数据分析工作。它平衡了理论、实践技能和作品集构建。",
            "stages": [
                {
                    "stage_number": 1,
                    "stage_title": "基础：掌握Python和SQL",
                    "stage_description": "构建任何数据岗位都必需的基础编程和数据库技能。",
                    "recommended_items": [
                        {"item_id": "DA001", "item_title": "Python零基础入门"},
                        {"item_id": "DA003", "item_title": "SQL与数据库入门"}
                    ],
                    "reasoning": "Python和SQL是数据分析的基石。此阶段确保您在进入更复杂的主题之前拥有坚实的基础。"
                },
                {
                    "stage_number": 2,
                    "stage_title": "核心技能：应用技术",
                    "stage_description": "学习处理和分析数据，并理解技术背后的统计学理论。",
                    "recommended_items": [
                        {"item_id": "DA002", "item_title": "面向数据科学的Python高级编程"},
                        {"item_id": "DA005", "item_title": "数据分析统计学基础"}
                    ],
                    "reasoning": "此阶段从基础语法转向实际应用，使您能够执行有意义的分析并正确解释结果。"
                },
                {
                    "stage_number": 3,
                    "stage_title": "进阶主题：机器学习导论",
                    "stage_description": "初步了解机器学习，以拓宽您的技能组合。",
                    "recommended_items": [
                        {"item_id": "DA006", "item_title": "机器学习概论"}
                    ],
                    "reasoning": "理解机器学习原理是就业市场上的一个关键差异化优势，并为更高级的职位打开大门。"
                },
                {
                    "stage_number": 4,
                    "stage_title": "终极目标：构建作品集与求职",
                    "stage_description": "将所有学到的技能应用到一个真实世界的项目中，并为进入就业市场做准备。",
                    "recommended_items": [
                        {"item_id": "DA007", "item_title": "数据分析师作品集项目"},
                        {"item_id": "DA008", "item_title": "数据分析师求职攻略"}
                    ],
                    "reasoning": "一个强大的作品集对于向雇主展示您的能力至关重要。这最后阶段将巩固您的学习成果，并专注于职业发展。"
                }
            ]
        }, indent=2, ensure_ascii=False)
    elif "outdoor adventure trip" in prompt.lower() or "户外探险旅行" in prompt.lower():
        return json.dumps({
            "plan_title": "班夫国家公园家庭户外探险计划",
            "plan_summary": "一个全面的家庭友好型户外旅行计划，涵盖从行前准备到现场活动的所有内容。重点是安全、所有年龄段的参与度以及体验班夫的精华。",
            "stages": [
                {
                    "stage_number": 1,
                    "stage_title": "第一阶段：规划与预订（行前2-3个月）",
                    "stage_description": "确保所有主要的预订都已完成，并检查旅行要求。",
                    "recommended_items": [
                        {"item_id": "DEST02", "item_title": "加拿大班夫国家公园"},
                        {"item_id": "ACT03", "item_title": "检查签证和旅行证件"},
                        {"item_id": "ACT02", "item_title": "预订露营地"}
                    ],
                    "reasoning": "这个初始阶段对于在像班夫这样的热门目的地确保位置至关重要，并确保所有旅行后勤工作都提前处理好，以避免最后一刻的压力。"
                },
                {
                    "stage_number": 2,
                    "stage_title": "第二阶段：装备与物资采购（行前1个月）",
                    "stage_description": "购买或收集所有必要的设备，以确保旅途安全舒适。",
                    "recommended_items": [
                        {"item_id": "GEAR01", "item_title": "防水徒步鞋"},
                        {"item_id": "GEAR02", "item_title": "全天候帐篷（4人）"},
                        {"item_id": "GEAR03", "item_title": "急救包"}
                    ],
                    "reasoning": "适当的装备对于安全和舒适至关重要，尤其是在家庭旅行中。此阶段专注于获取被认为是户外探险关键的核心物品。"
                },
                {
                    "stage_number": 3,
                    "stage_title": "第三阶段：现场活动与探索（旅行期间）",
                    "stage_description": "在目的地参与难忘且适合家庭的活动。",
                    "recommended_items": [
                        {"item_id": "ACT_CANOE", "item_title": "在路易斯湖上划皮划艇"},
                        {"item_id": "ACT_HIKE", "item_title": "在约翰斯顿峡谷进行家庭友好型徒步"}
                    ],
                    "reasoning": "这个阶段是体验的核心。推荐的活动是班夫的标志性活动，并且适合家庭，确保每个人都能享受到一次有趣的旅行。"
                }
            ]
        }, indent=2, ensure_ascii=False)
    else:
        return json.dumps({"error": "无法为该目标生成计划。"})


class GoalPlanner:
    def __init__(self, user_profile: Dict[str, Any]):
        self.user_profile = user_profile
        self.plan = None

    def generate_plan(self, goal: str, constraints: str, domain: str):
        """
        生成推荐规划的主方法。
        """
        print(f"--- 开始为目标生成规划: '{goal}' ---")
        # 1. RAG：从知识库中检索相关信息
        knowledge_base = retrieve_knowledge(domain)
        knowledge_base_str = json.dumps(knowledge_base, indent=2, ensure_ascii=False)

        # 2. Prompt工程：构建完整的Prompt
        prompt = PLANNING_PROMPT_TEMPLATE.format(
            user_profile=json.dumps(self.user_profile, indent=2, ensure_ascii=False),
            user_goal=goal,
            user_constraints=constraints,
            knowledge_base_str=knowledge_base_str
        )

        # 3. LLM调用：从（模拟的）LLM获取规划
        llm_response_str = _call_simulated_llm(prompt)

        # 4. 解析响应
        try:
            self.plan = json.loads(llm_response_str)
            print("--- [Planner] 成功解析LLM响应。规划已生成。 ---")
        except json.JSONDecodeError:
            print("--- [Planner] 错误：无法解析来自LLM的JSON响应。 ---")
            self.plan = {"error": "来自LLM的无效JSON响应。"}

        return self.plan

    def display_plan(self):
        """
        将生成的规划以美观的格式打印到控制台。
        """
        if not self.plan or "error" in self.plan:
            print("\n没有可显示的规划或发生了错误。")
            return

        print("\n" + "=" * 50)
        print(f" 规划: {self.plan.get('plan_title')}")
        print("=" * 50)
        print(f"\n摘要: {self.plan.get('plan_summary')}\n")

        for stage in self.plan.get('stages', []):
            print(f"--- 阶段 {stage['stage_number']}: {stage['stage_title']} ---")
            print(f"  描述: {stage['stage_description']}")
            print(f"  推荐项目:")
            for item in stage.get('recommended_items', []):
                print(f"    - {item['item_title']} (ID: {item['item_id']})")
            print(f"   理由: {stage['reasoning']}\n")
        print("=" * 50)

    def adjust_plan_with_feedback(self, feedback: str):
        """
        模拟根据用户反馈调整规划。
        """
        print(f"\n--- 收到用户反馈: '{feedback}' ---")
        print("--- 触发重新规划流程... ---")
        # 在真实系统中，应将此反馈添加到约束条件中，并再次调用 generate_plan()。
        # 在此模拟中，仅为展示概念。

        new_constraints = f"原始约束不理想。需要考虑的新用户反馈: '{feedback}'"

        # 为了演示，假设用户正在学习数据分析，并觉得第一步太难。
        if "太难" in feedback or "too difficult" in feedback:
            self.generate_plan(
                goal="我想学习数据分析，但是希望从更容易的内容开始。",
                constraints=new_constraints,
                domain="data_analysis"
            )

